/* Copyright (C) 2010 Fredrique Samuels, fredriquesamuels@gmail.com */

/*
  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "sliderbar.h"

namespace tri {
namespace ui {

extSliderBar::extSliderBar() :
	tri::ui::extPanel(),
	mSensitivity(1),
	mValue(0),
	mMaxValue(1.0),
	mMinValue(0.0){
	addComponent(&mSliderButton);
}

extSliderBar::~extSliderBar() {
}

void extSliderBar::setSliderButtonWidth(float w){
	TVector v = mSliderButton.getSize();
	mSliderButton.setSize(w,v.y,v.z);
}

void extSliderBar::setSliderButtonHeight(float h){
	TVector v = mSliderButton.getSize();
	mSliderButton.setSize(v.x,h,v.z);
}

float extSliderBar::getValue(){
	return mValue;
}
	
void extSliderBar::setValue(float v){
	mValue = v < mMinValue ? mMinValue : v;
	mValue = v > mMaxValue ? mMaxValue : v;
	updateSliderPosition();
	emit(tri::VALUE_CHANGED);
}
	
void extSliderBar::setMaximumValue(float v){
	if(v <= mMinValue){
		return;
	}
	mMaxValue = v;
	updateSliderPosition();
}
	
void extSliderBar::setMinimumValue(float v){
	if(v >= mMaxValue){
		return;
	}
	mMinValue = v;
	updateSliderPosition();
}

float extSliderBar::getMaximumValue(){
	return mMaxValue;
}

float extSliderBar::getMinimumValue(){
	return mMinValue;
}

void extSliderBar::update(){
	updateSliderPosition();
	extPanel::update();
}

void extSliderBar::setStyle(std::string style){
	extPanel::setStyle(style);
	mSliderButton.setStyle(style+std::string(".ThumbButton"));
}


//===================================================================

extHorizontalSlider::extHorizontalSlider():extSliderBar(){
	setSize(60,16,0);
	mHorizontalSliderButtonManager = new HorizontalSliderButtonManager(this);
	setSliderButtonWidth(10);
	setStyle("DefaultHSliderBarStyle");
}

extHorizontalSlider::~extHorizontalSlider(){
	delete mHorizontalSliderButtonManager;
}


void extHorizontalSlider::update(){
	extSliderBar::update();
	TVector v = getSize();
	setSliderButtonHeight(v.y);
}

void extHorizontalSlider::updateSliderPosition(){
	tri::TVector sl_size =  getSize();
	tri::TVector btn_pos =  mSliderButton.getPosition();
	tri::TVector btn_size =  mSliderButton.getSize();
		
	float range = mMaxValue - mMinValue;
	float perc = (mValue-mMinValue) / range;
	float _pos = (sl_size.x-btn_size.x)*perc;
	btn_pos.x = _pos;// - (sl_size.x/2-btn_size.x/2);
	
	mSliderButton.setPosition(btn_pos);
}

//===================================================================


extHorizontalSlider::HorizontalSliderButtonManager::HorizontalSliderButtonManager(extHorizontalSlider* slider){
	mSlider = slider;
	if(mSlider!=NULL){
//		mSlider->mSliderButton.MOUSE_DRAG.connect(this,&HorizontalSliderButtonManager::onMouseDrag);
		mSlider->mSliderButton.connect<HorizontalSliderButtonManager>(tri::MOUSE_DRAG,this,&HorizontalSliderButtonManager::onMouseDrag);
	}
}

extHorizontalSlider::HorizontalSliderButtonManager::~HorizontalSliderButtonManager(){}

void extHorizontalSlider::HorizontalSliderButtonManager::onMouseDrag(){
	tri::TMouseEvent event = tri::getMouseEvent();
	if(mSlider!=NULL && event.getRelativeX() != 0 ){
		tri::TVector sl_size =  mSlider->getSize();
		tri::TVector btn_pos =  mSlider->mSliderButton.getPosition();
		tri::TVector btn_size =  mSlider->mSliderButton.getSize();
		btn_pos.x += mSlider->mSensitivity*event.getRelativeX();
		
		btn_pos.x = btn_pos.x < 0 ? 0 : btn_pos.x;
		btn_pos.x = btn_pos.x > sl_size.x-btn_size.x ? sl_size.x-btn_size.x : btn_pos.x;
		
		mSlider->mSliderButton.setPosition(btn_pos);
		
		float range = mSlider->mMaxValue - mSlider->mMinValue;
		
		mSlider->mValue = mSlider->mMinValue + ( btn_pos.x / (sl_size.x-btn_size.x) ) * range;
		mSlider->emit(tri::VALUE_CHANGED);
	}
}

//===================================================================

extVerticalSlider::extVerticalSlider():extSliderBar(){
	setSize(16,60,0);
	mVerticalSliderButtonManager = new VerticalSliderButtonManager(this);
	setSliderButtonHeight(10);
	setStyle("DefaultVSliderBarStyle");
}

extVerticalSlider::~extVerticalSlider(){
	delete mVerticalSliderButtonManager;
}


void extVerticalSlider::update(){
	extSliderBar::update();
	TVector v = getSize();
	setSliderButtonWidth(v.x);
}

void extVerticalSlider::updateSliderPosition(){
	tri::TVector sl_size =  getSize();
	tri::TVector btn_pos =  mSliderButton.getPosition();
	tri::TVector btn_size =  mSliderButton.getSize();
		
	float range = mMaxValue - mMinValue;
	float perc = (mValue-mMinValue) / range;
	float _pos = (sl_size.y-btn_size.y)*perc;
	btn_pos.y = _pos;// - (sl_size.y/2-btn_size.y/2);
	
	mSliderButton.setPosition(btn_pos);
}

//===================================================================


extVerticalSlider::VerticalSliderButtonManager::VerticalSliderButtonManager(extVerticalSlider* slider){
	mSlider = slider;
	if(mSlider!=NULL){
//		mSlider->mSliderButton.MOUSE_DRAG.connect(this,&VerticalSliderButtonManager::onMouseDrag);
		mSlider->mSliderButton.connect<VerticalSliderButtonManager>(tri::MOUSE_DRAG,this,&VerticalSliderButtonManager::onMouseDrag);
	}
}

extVerticalSlider::VerticalSliderButtonManager::~VerticalSliderButtonManager(){}

void extVerticalSlider::VerticalSliderButtonManager::onMouseDrag(){
	tri::TMouseEvent event = tri::getMouseEvent();
	if(mSlider!=NULL && event.getRelativeY() != 0 ){
		tri::TVector sl_size =  mSlider->getSize();
		tri::TVector btn_pos =  mSlider->mSliderButton.getPosition();
		tri::TVector btn_size =  mSlider->mSliderButton.getSize();
		btn_pos.y -= mSlider->mSensitivity*event.getRelativeY();
		
		btn_pos.y = btn_pos.y < 0 ? 0 : btn_pos.y;
		btn_pos.y = btn_pos.y > sl_size.y-btn_size.y ? sl_size.y-btn_size.y : btn_pos.y;
		
		mSlider->mSliderButton.setPosition(btn_pos);
		
		float range = mSlider->mMaxValue - mSlider->mMinValue;
		
		mSlider->mValue = mSlider->mMinValue + ( btn_pos.y / (sl_size.y-btn_size.y) ) * range;
		mSlider->emit(tri::VALUE_CHANGED);
	}
}


}
}
